    一个基于时间生成编码的工具类，主要是考虑反字符长度的问题，使用方式：

    string no = "自定义前缀" + NathanFlake.Singleton.NextId();
    目前这个如果1秒钟之内并发，最多生成34个编号，因为使用的是34进制，编号最后位我只放了1位，大家可以自行调整。
    
    /**+++++++++++++++++++++++++++
     * 说明：纳森算法
     *
     * 编写：[yohuy@qq.com]
     * 创建：[2020-12-26 11:12]
     * 修改：[2020-12-26 13:48]
     *+++++++++++++++++++++++++++*/
    public class NathanFlake
    {
        static readonly object _locker = new object();
        static NathanFlake _Singleton;
        int _maxQueLength = 60;
        int _hexNum = 34;
        string[] _tsStrAry;
        Queue<string> _seedQueue;
        Dictionary<string, List<string>> _seedDict;
        private NathanFlake()
        {
            // TODO [yohuy@qq.com 2020-12-26 13:50]
            // 后期加入workId、datacenterId，优化算法作为作为分布式ID生成算法
            _seedQueue = new Queue<string>();
            _seedDict = new Dictionary<string, List<string>>();
            _tsStrAry = new string[_hexNum];
            int index = 0;
            for (int i = 0; i < 36; i++, index++)
            {
                if (i < 10)
                {
                    _tsStrAry[index] = ((char)(i + 48)).ToString();
                }
                else
                {
                    _tsStrAry[index] = ((char)(i + 65 - 10)).ToString();
                    // [yohuy@qq.com 2020-12-26 13:55]
                    // 参考车牌号生成规则，[1-Z]去掉字母O、I，保留数字0、1
                    if (_tsStrAry[index] == "O" || _tsStrAry[index] == "I")
                    {
                        index--;
                    }
                }
            }
        }
        /// <summary>
        /// 纳森算法实例
        /// </summary>
        public static NathanFlake Singleton
        {
            get
            {
                if (_Singleton == null)
                {
                    lock (_locker)
                    {
                        if (_Singleton == null)
                        {
                            _Singleton = new NathanFlake();
                        }
                    }
                }
                return _Singleton;
            }
        }

        /// <summary>
        /// 获取生成的ID
        /// </summary>
        /// <returns></returns>
        public string NextId()
        {
            lock (_locker)
            {
                var res = Loop(DateTime.Now);
                if (_seedQueue.Count >= _maxQueLength)
                {
                    var expKey = _seedQueue.Dequeue();
                    _seedDict.Remove(expKey);
                }
                return res;
            }
        }

        /// <summary>
        /// 循环获取ID
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        private string Loop(DateTime date)
        {
            var seed = date.ToString("yy.MM.dd.HH.mmss");
            var seedAry = seed.Split('.');

            var resAry = new string[6];
            resAry[0] = _tsStrAry[int.Parse(seedAry[0]) % _hexNum];
            resAry[1] = _tsStrAry[int.Parse(seedAry[1])];
            resAry[2] = _tsStrAry[int.Parse(seedAry[2])];
            resAry[3] = _tsStrAry[int.Parse(seedAry[3])];
            resAry[4] = seedAry[4];

            int count = 0;
            while (true)
            {
                if (count >= _hexNum)
                {
                    // [yohuy@qq.com 2020-12-26 14:35]
                    // 因为当前种子值设为34，1秒钟只能生成最多34个ID
                    // System.Threading.Thread.Sleep(1000);
                    return Loop(date.AddSeconds(1));
                }
                resAry[5] = _tsStrAry[count];
                if (ValidSeed(resAry[4], resAry[5]))
                {
                    return string.Concat(resAry);
                }
                count++;
            }
        }

        /// <summary>
        /// 验证唯一性
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        private bool ValidSeed(string key, string val)
        {
            bool b = false;
            List<string> vals;
            if (_seedDict.TryGetValue(key, out vals))
            {
                if (!vals.Contains(val))
                {
                    vals.Add(val);
                    b = true;
                }
            }
            else
            {
                _seedQueue.Enqueue(key);
                _seedDict.Add(key, new List<string> { val });
                b = true;
            }
            return b;
        }
    }